早安!歡迎進入前端的世界
今天來介紹ClojureScript專案,並且寫一個會跳出來跟我們說Hello Ironman的網頁~
當我們在從0開始打造一個JavaScript專案時,可能要考慮蠻多的問題
第三方套件雖然方便好用,但也會造成page loading速度變慢。
ClojureScript有許多很棒的 data structures
像是collection、strings、math, 以及狀態管理等。
就可以簡化上述麻煩的決策。
另一方面,ClojureScript使用Google Closure Compiler轉譯工具與 Closure Library函式庫,而且瀏覽器相容性的問題也比較少。讓我們工程師可以把注意力聚焦在用coding處理問題的本質上。
我蠻喜歡Learn ClojureScript畫的這張圖:
ClojureScript的Expressions
、Sequence
及functional programming的語法特色,可以帶我們處理High-Level
層級的問題。
工欲善其事,必先利其器。快速產生ClojureScript(或者是Clojure)專案,我們可以用負責自動化build project的Leiningen。
https://codeberg.org/leiningen/leiningen
安裝Leiningen在Mac上十分簡單,透過Homebrew安裝就可以了
brew install Leiningen
安裝好了Leiningen,
就可以透過new figwheel
建立cljs template project的指令,
一鍵建立專案!( 一鍵建立的時候都會覺得自己是神)
❯ lein new figwheel hello-world
Retrieving figwheel/lein-template/0.5.20-5/lein-template-0.5.20-5.pom from clojars
Retrieving figwheel/lein-template/0.5.20-5/lein-template-0.5.20-5.jar from clojars
Generating fresh 'lein new' figwheel project.
Change into your 'hello-world' directory
Then run 'lein figwheel'
Wait for it to finish compiling
A browser window should open to the demo application, if not
then open 'http://localhost:3449/index.html' in your browser
$ lein new [TEMPLATE] NAME # generate a new project skeleton
$ lein test [TESTS] # run the tests in the TESTS namespaces, or all tests
$ lein repl # launch an interactive REPL session
$ lein run -m my.namespace # run the -main function of a namespace
$ lein uberjar # package the project and dependencies as standalone jar
$ lein deploy clojars # publish the project to Clojars as a library
由於我們是做前端專案
所以根據command line的提示
Then run 'lein figwheel'
Wait for it to finish compiling
A browser window should open to the demo application, if not
then open 'http://localhost:3449/index.html' in your browser
等等開啟瀏覽器運行code的指令是 lein figwheel
從此時此刻開始,我們會把ClojureScript
簡稱為cljs
的縮寫啦!
首先用tree
這個套件來介紹一下資料夾結構
~/Projects/hello-world
❯ tree -a
.
├── .gitignore
├── README.md
├── dev
│ └── user.clj
├── project.clj
├── resources
│ └── public
│ ├── css
│ │ └── style.css
│ └── index.html
└── src
└── hello_world
└── core.cljs
其中
src/hello_world
資料夾代表這個專案的namespacecore.cljs
主程式的檔案,副檔名為cljs,我們主要會在裡面codingclj
和 cljs
的區分身為Clojure/ClojureScript新手,在查資料的時候一開始也被搞混,
我查到的網頁是到底是要建立Clojure專案還是cljs專案呢?
如果我們是用lein new app
的方式,建立的是clj
專案
所以我一開始也搞錯了!XD (以下的專案已被丟進垃圾桶O_Q)
比較一下專案內容
core.clj
主程式:(ns cljs-it-ironman.core)
(defn hello
[x]
(println x "Hello, World!"))
no no no這不是cljs專案(搖手指)
就只會有副檔名為clj
的檔案
(defproject cljs-it-ironman "0.1.0-SNAPSHOT"
:description "My first cljs project"
:url "https://ithelp.ithome.com.tw/users/20111177/articles"
:license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.eclipse.org/legal/epl-2.0/"}
:dependencies [[org.clojure/clojure "1.11.1"]]
:repl-options {:init-ns cljs-it-ironman.core})
project.clj
爲專案的配置描述文件(專案的description、license、使用到的套件以compile選項)
core.cljs
& project.clj
但因為我們的目的是要做一個前端專案
就沒有core.clj
這個檔案了。副檔名會是core.cljs
,
core裡面長的樣子就會很不一樣啦!會有狀態管理(state management),並且可以設定js reload的時候的機制
(ns hello-world.core
(:require))
(enable-console-print!)
(println "This text is printed from src/hello-world/core.cljs. Go ahead and edit it and see reloading in action.")
;; define your app data so that it doesn't get over-written on reload
(defonce app-state (atom {:text "Hello world!"}))
(defn on-js-reload [])
;; optionally touch your app-state to force rerendering depending on
;; your application
;; (swap! app-state update-in [:__figwheel_counter] inc)
project.clj
內的defproject
也複雜許多(defproject hello-world "0.1.0-SNAPSHOT"
:description "My first cljs project"
:url "https://ithelp.ithome.com.tw/users/20111177/articles"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:min-lein-version "2.9.1"
:dependencies [[org.clojure/clojure "1.10.0"]
[org.clojure/clojurescript "1.10.773"]
[org.clojure/core.async "0.4.500"]]
:plugins [[lein-figwheel "0.5.20"]
[lein-cljsbuild "1.1.7" :exclusions [[org.clojure/clojure]]]]
:source-paths ["src"]
:cljsbuild {:builds
[{:id "dev"
:source-paths ["src"]
:figwheel {:on-jsload "hello-world.core/on-js-reload"
:open-urls ["http://localhost:3449/index.html"]}
:compiler {:main hello-world.core
:asset-path "js/compiled/out"
:output-to "resources/public/js/compiled/hello_world.js"
:output-dir "resources/public/js/compiled/out"
:source-map-timestamp true
;; To console.log CLJS data-structures make sure you enable devtools in Chrome
;; https://github.com/binaryage/cljs-devtools
:preloads [devtools.preload]}}
{:id "min"
:source-paths ["src"]
:compiler {:output-to "resources/public/js/compiled/hello_world.js"
:main hello-world.core
:optimizations :advanced
:pretty-print false}}]}
:figwheel {;; :http-server-root "public" ;; default and assumes "resources"
;; :server-port 3449 ;; default
;; :server-ip "127.0.0.1"
:css-dirs ["resources/public/css"] ;; watch and update CSS
}
:profiles {:dev {:dependencies [[binaryage/devtools "1.0.0"]
[figwheel-sidecar "0.5.20"]]
;; need to add dev source path here to get user.clj loaded
:source-paths ["src" "dev"]
;; need to add the compiled assets to the :clean-targets
:clean-targets ^{:protect false} ["resources/public/js/compiled"
:target-path]}})
我們可以看到js裡的套件相依性目前有安裝 figwheel-sidecar
和 binaryage/devtools
也得知到,ClojureScript complier編譯為javascript後會變成這支檔案 resources/public/js/compiled/hello_world.js
我們來hello-world namespace
下插一句javascript的alert:
(ns hello-world.core
(js/alert "Hello Ironman!")
並且以 lein figwheel
啟動http-server
~/Projects/hello-world
❯ lein figwheel
Retrieving lein-figwheel/lein-figwheel/0.5.20/lein-figwheel-0.5.20.pom from clojars
Retrieving lein-cljsbuild/lein-cljsbuild/1.1.7/lein-cljsbuild-1.1.7.pom from clojars
Retrieving lein-figwheel/lein-figwheel/0.5.20/lein-figwheel-0.5.20.jar from clojars
Retrieving lein-cljsbuild/lein-cljsbuild/1.1.7/lein-cljsbuild-1.1.7.jar from clojars
Figwheel: Cutting some fruit, just a sec ...
IT鐵人又排除萬難、順利地完成了Day21的任務了!:)
ClojureScript Release - Rich Hickey
https://www.youtube.com/watch?v=tVooR-dF_Ag